Part I: R Introduction
What is R?
R is a programming language used for statistical analysis and graphics. It is based on S-plus, which itself was based on S, a programming language originally developed by AT&T.
Why R?
- Open source, cross-platform, and free
- Great for reproducibility
- Interdisciplinary and extensible
- Tons of learning resources
- Works on data of all shapes and sizes
- Produces high-quality graphics
- Large and welcoming community
R: Object-Oriented Programming
Unlike many other statistical software such as SAS and SPSS, R will not spit out a mountain of output on the screen.
Instead, R returns an object containing all the results. You, as an user, have the flexibility to choose which result to be extracted or reported.
R: Functional Programming
This feature allows us to write faster yet more compact code. For example, a common theme in R programming is avoidance of explicit iteration. Unlike many other statistical softwares, explicit loops are discouraged.
Instead, R provides some functions that could allow us to express iterative behavior implicitly.
R: Polymorphic
R is also polymorphic, which means that a single function can be applied to different types of inputs (much more user friendly).
Such a function is called a generic function (If you are a C++ programmer, you have seen a similar concept in virtual functions).
Polymorphic - Example
Lets look at one example plot()
- Plot a vector of numbers
- Plot some model results
No matter which purpose, we use the same function.
data<-c(1,2,3,4)
plot(data)

# Regression Analysis
par(mfrow=c(2,2),mar=c(2,4,2,2))
results<-lm(speed ~ dist,data=cars)
plot(results)

Why R Studio?
R Interface is ugly!
Many students in this class are much more familiar with Windows operation system and have never been exposed programming before, so we will use R studio, one of the free Graphical User Interfaces (GUIs) that have been developed for R.
R studio should really be considered as integrated development environments (IDEs), since it is aimed more toward programming.
Easy publishing of reproducible documents such as reports, interactive visualizations, presentations, and websites.
R Studio: A short tour
Initial Start
When you first (like very first time) open R studio you will see three panels.

Console

- Every time you launch RStudio, it will have the same text at the top of the console telling you the version of R that you’re running.
- Below that information is the prompt,
> . As its name suggests, this prompt is really a request, a request for a command.
- Initially, interacting with R is all about typing commands and interpreting the output.
- These commands and their syntax have evolved over decades (literally) and now provide what many users feel is a fairly natural way to access data and organize, describe, and invoke statistical computations.
The console is where you type commands and have them immediately performed.
Environment
The panel in the upper right contains your workspace (aka Environment)

- This shows you a list of objects/variables that R has saved.
- For example here a value of
3 has been assigned to the object a.
History
Up here there is an additional tab to see the history of the commands that you’ve previously entered.

Files
The files tab allows you to open code/script files within R studio.

Plots
Any plots that you generate will show up in the panel in the lower right corner.

Help
To check the syntax of any function in R, type ? in front of the function name to pull up the help file.

For example here I typed ?mean to get the help file for the mean function. The help files are not always the most useful but are usually a good place to start.
Script File The top left is your editor window, where you write code or script, the console is now at the bottom. I usually change it

The picture above illustrates my preferred style in R Studio.
R Script
Most of R users typically submit commands to R by typing either in console or editor panel, rather than clicking a mouse in a Graphical User Interface (GUI).
In this class, we will make extensive use of scripts. A Script is nothing but a collection of commands and procedures that the coder performed to get to their results and conclusions..
There are at least two advantages of doing so:
- As explained earlier, this allows us to run a bunch of results altogether by putting a collection of commands in a file.
- It is also a lot more transparent and straightforward to share and replicate what you have done.
This will always be our approach in this class!!!
Exercise
Task 1: Create a script file
- Open R Studio and go to
File > New > R Script.
This will open a blank text document.
- Two alternative ways are:
- CTRL + SHIFT + N or
- press the button marked “+”, just below File, and select R Script
- In the document, type
x = 5 # Assign the variable x a value of 5
x == 5 # Does x = 5? Notice the double ==
Highlight both lines of code and click the button marked “Run”. If everything is working correctly, the console should display TRUE.
OR, pressing CTRL + ENTER or COMMAND + RETURN depending on whether you’re running Mac OSX, Linux or Windows.
- Go to “File > Save As”, and choose a file name.
Part III: R Data types
Data types in R
You have observed a few of the different data types in the earlier sections. Here, we will formally discuss them. Some of the most basic data types we will cover are:
- Decimal values like 4.5 are called numerics.
- Natural numbers like 4 are called integers. Integers are also numerics.
- Boolean values (TRUE or FALSE) are also called logical.
- Text (or string) values are called characters.
You can check the type of data by using class().
x <- "Lyrics to Virginia Tech Fight Song!"
class(x)
[1] "character"
x2 <- c("TRUE", "FALSE")
x2 <- as.logical(x2) #Declare the data type
x2
[1] TRUE FALSE
[1] "logical"
x <- 1:20
x %% 4 #x mod 4
[1] 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 0
[1] FALSE FALSE FALSE TRUE FALSE FALSE FALSE TRUE FALSE FALSE
[11] FALSE TRUE FALSE FALSE FALSE TRUE FALSE FALSE FALSE TRUE
[1] "logical"
Vectors
A vector is the most common and basic data type in R, and is pretty much the workhorse of R. A vector is characterized by a series of values, which can be either numbers or characters. We can assign a series of values to a vector using the c() function.
In short, vectors are most useful when we have a collection of data points.
Here c() stands for concatenate or combine.
[1] 1 2 3 4
[1] 1 2 3 4
(v <- seq(from = 0, to = 0.5, by = 0.1))
[1] 0.0 0.1 0.2 0.3 0.4 0.5
#A vector can also contain characters:
(v_colors <- c("blue", "yellow", "light green") )
[1] "blue" "yellow" "light green"
Notice that by encasing the beginning and end of the assignment lines in parentheses, we immediately print the stored values.
Subsetting vectors (Indexing/reassigning elements)
We are able to index (collect subsets of our variables) by using squared brackets. Unlike python, for example, R’s indexing begins from 1.
v_colors[2] # We are trying to extract the second element of the vector, v_colors
[1] "yellow"
v_colors[c(1,3)] # We can use the concatenation function to get nonconsecutive elements. Here, we are trying to extract elements in positions 1 and 3.
[1] "blue" "light green"
How would your extract elements 1:9, 15, 19, 20 and 21:30 in zz below?
set.seed(1234)
zz <- rnorm(100)
Answer:
zz[c(1:19,15, 19, 20:30)]
[1] -1.20706575 0.27742924 1.08444118 -2.34569770 0.42912469
[6] 0.50605589 -0.57473996 -0.54663186 -0.56445200 -0.89003783
[11] -0.47719270 -0.99838644 -0.77625389 0.06445882 0.95949406
[16] -0.11028549 -0.51100951 -0.91119542 -0.83717168 0.95949406
[21] -0.83717168 2.41583518 0.13408822 -0.49068590 -0.44054787
[26] 0.45958944 -0.69372025 -1.44820491 0.57475572 -1.02365572
[31] -0.01513830 -0.93594860
We can replace elements in specific positions. Below, we replace the second and third colors with red and purple.
(v_colors[2:3] <- c("red", "purple") )
[1] "red" "purple"
Sometimes it might be more convenient to get rid of particular elements instead. For example, I might want to extract all but the first 5 elements of a vector, or all but the 15th element. We might find it easier to use a negative index here.
[1] 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
# We could have done that in one go as well
x[-c(1:3)]
[1] 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Conditional subsetting
Another common way to subset is by using a logical vector. TRUE will select the element with the same index, while FALSE will not. Typically, these logical vectors are not typed by hand, but are the output of other functions or logical tests such as:
[1] 100 101 102 103 104 105 106 107 108 109 110
x >105 # returns TRUE or FALSE depending on which elements that meet the condition
[1] FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE TRUE TRUE
[11] TRUE
select <- x > 105
x[select]
[1] 106 107 108 109 110
If we would like the elements that evaluate to FALSE instead, we could easily use the ! (NOT) operator
[1] 100 101 102 103 104 105
You can combine multiple tests using:
We can test whether x is between the range 103 and 106:
[1] 103 104 105 106
x is greater than 103 but (AND) less than or equal to 106
x[x <= 106 & x > 103] # order of subsetting does not matter here!
[1] 104 105 106
x is less than 103 or greater than 106
[1] 100 101 102 106 107 108 109 110
Sometimes we will need to search for certain strings in a vector. With multiple conditions, it becomes difficult to use the “OR” operator |. The function %in% allows you to test if any of the elements of a search vector are found:
animals <- c("mouse", "rat", "dog", "cat")
animals[animals == "cat" | animals == "rat"] # returns both rat and cat
[1] "rat" "cat"
animals %in% c("rat", "cat", "dog", "duck", "goat")
[1] FALSE TRUE TRUE TRUE
animals[animals %in% c("rat", "cat", "dog", "duck", "goat")]
[1] "rat" "dog" "cat"
Names of a vector
Let’s say that we want to know which color robe each of 3 patients is wearing, we can assign names to the vector of colors.
[1] "blue" "red" "purple"
names(v_colors) <- c("Thomas", "Liz", "Tucker")
v_colors
Thomas Liz Tucker
"blue" "red" "purple"
Algebraic Operations of Vectors
x <- c(1,2,3)
y <- c(4,5,6)
# component-wise addition
x+y
[1] 5 7 9
# component-wise multiplication
x*y
[1] 4 10 18
# What happens to the following
y^x # or y**x
[1] 4 25 216
Repeating Vector in R
# Would this work?
c(1,2,3,4) + c(1,2)
[1] 2 4 4 6
# Would this work?
c(1,2,3) + c(1,2)
Warning in c(1, 2, 3) + c(1, 2) :
longer object length is not a multiple of shorter object length
[1] 2 4 4
Why the weird results?
- When you are adding vectors of unequal size, if the long one is a multiple of the short one,
R automatically repeats the short one to fill in the operation.
[1] 2 4 6
Matrix
Create a new matrix
(matrix<-matrix(1:16, nrow = 4, byrow = TRUE))
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8
[3,] 9 10 11 12
[4,] 13 14 15 16
Note that : means every number from 1 to 4. In the matrix() function:
- The first argument is the collection of elements that
R will arrange into the rows and columns of the matrix. Here, we use 1:16 which is a shortcut for c(1, 2, 3, 4, … 16).
- The argument
byrow indicates that the matrix is filled by the rows. If we want the matrix to be filled by the columns, we use byrow = FALSE.
- The argument
nrow indicates that the matrix should have 4 rows.
Selection of Matrix Elements
Selection of the matrix elements are similar to vectors except we have two dimensions over which to subset- rows and columns.
# matrix[r,c] #Standard form of the matrix.
matrix[1,2] #Extract element in the first row and second column
[1] 2
#Extract the entire first row and second columns
matrix[,1:2]
[,1] [,2]
[1,] 1 2
[2,] 5 6
[3,] 9 10
[4,] 13 14
Assign dimension names to Matrix
rownames(matrix) <- c("Yes", "No", "Perhaps", "Maybe")
colnames(matrix) <- c("Apple", "Pear", "Banana", "Grapes")
matrix
Apple Pear Banana Grapes
Yes 1 2 3 4
No 5 6 7 8
Perhaps 9 10 11 12
Maybe 13 14 15 16
Dimension of a matrix vs vector
x <- c(1,2,3)
matrix<-matrix(1:4, byrow = TRUE, nrow = 2)
length(x)
[1] 3
[1] 4
[1] 2 2
NULL
Lists
R doesn’t like vectors to have different types: c(TRUE, 1, "Frank") becomes c("TRUE", "1", "Frank"). But storing objects with different types is absolutely fundamental to data analysis. R has a different type of object besides a vector used to store data of different types side-by-side: a list:
[1] "TRUE" "1" "Frank"
x <- list(TRUE, 1, "Frank")
x
[[1]]
[1] TRUE
[[2]]
[1] 1
[[3]]
[1] "Frank"
Many different things not necessarily of same length can be put together.
x <- list(c(1:5), c("a", "b","c"), c(TRUE, FALSE), c(5L, 6L))
x
[[1]]
[1] 1 2 3 4 5
[[2]]
[1] "a" "b" "c"
[[3]]
[1] TRUE FALSE
[[4]]
[1] 5 6
Dataframes
- Data frames are like spreadsheet data, rectangular with rows and columns.
- Ideally each row represents data on a single observation and each column contains data on a single variable, or characteristic, of the observation.
- It represents the data in a tabular format where the columns are vectors that all have the same length. Because columns are vectors, each column must contain a single type of data (e.g., characters, integers, factors).
- We can open a data viewer window to see the contents of
R’s iris data frame by typing.
- We will be working with spreadsheets a lot.
Create a data frame
Data frame with Harry Potter characters
name <- c("Harry", "Ron", "Hermione", "Hagrid", "Voldemort")
height <- c(176, 175, 167, 230, 180)
gpa <- c(3.4, 2.8, 4.0, 2.2, 3.4)
df_students <- data.frame(name, height, gpa)
df_students
Alternative way of creating DF
df_students <- data.frame(name = c("Harry", "Ron", "Hermione", "Hagrid", "Voldemort"),
height = c(176, 175, 167, 230, 180),
gpa = c(3.4, 2.8, 4.0, 2.2, 3.4))
df_students
Adding variable
df_students$good <- c(1, 1, 1, 1, 0)
df_students
Features of the DF
dim(df_students)
df_students[2, 3] #Ron's GPA
df_students$gpa[2] #Ron's GPA
df_students[5, ] #get row 5
df_students[3:5, ] #get rows 3-5
df_students[, 2] #get column 2 (height)
df_students$height #get column 2 (height)
df_students[, 1:3] #get columns 1-3
df_students[4, 2] <- 255 #reassign Hagrid's height
df_students$height[4] <- 255 #same thing as above
df_students
Exercise
Now that you are equipped with the basic, go ahead and take the following Datacamp Course, R Intro on Datacamp. Your invitations should now be in your inbox.
Part IV: Working directories
You can use the
command to obtain the current directory R is using.
It is good practice to set the working directory location to where the files and data are stored.
- Consider setting your working directory to a folder called AAEC4984, AAEC5484, or STAT5484 on your desktop (for example).
Creating Directory and Set working directory
Windows
setwd("C:/users/[your user name]/Desktop/AAEC4984/")
# OR
setwd("C:\\users\\[your user name]\\Desktop\\AAEC4984\\")
# notice the double backslashes
Mac
setwd("~/Desktop/AAEC4984")
- To check whether the wd is correct, we again use
- To obtain a list of the names of files or folders in the working directory, we can use
- To create a new folder in your directory we can use
dir.create("[Folder name]")
Importing data
R allows us to import several file types. I will discuss 3 that we are most likely to use in this course.
- Text files
- Data sometimes come with headers (the first row is variable names, not actual data!) You need to tell R that!
textdata<-read.table("examples/hogsdata.txt",header=T)
- CSV files :
- xlsx files (requires openxlsx package)
xlsxdata <- read.csv("examples/hogsdata.xlsx", ... )
Functions & Packages
Functions are “canned scripts” that automate more complicated sets of commands including operations assignments, etc. For the purpose of this course, we will use a lot of functions that are built both in base R (that is, they are predfined) or available through R packages (discuss below).
A function usually takes one or more inputs called arguments, and often (but not always) return a value.
Consider for example, taking the average of a set of random numbers (x).
set.seed(124)
x <- rnorm(6) * 100
(round(x, digits=2)) # round function => 2dp
[1] -138.51 3.83 -76.30 21.23 142.55 74.45
If we were to do this manually, we would:
- Sum up the values
- Get the number of observations
- Divide sum by total number of observations
Using R’s built in mean function we can do all three steps internally and cross check against our manual calculations.
[1] 4.542439
meanx == mean(x) # cross validation
[1] TRUE
Installing Packages
Since R is an Open Source software program, thousands of people contribute to the software. They do this by writing commands (called functions) to make a particular analysis easier, or to make a graphic prettier.
When you download R, you get access to a lot of functions that we will use. However the other user-written packages we use for our analyses will make our lives much easier.
For example, though we can use the plot command for standard graphics, you will quickly see that we can get much better looking time graphs using the fpp2 package (which also uses another package called ggplot2).
Installing Packages
To install the fpp2 package, we can use the command
We will need to install a package only once in R.
Now that you have the fpp2 package installed, we can check to see if it is in use
Lastly, in order to use the package, we will need to load the library
Using libraries
The fpp2 package contains a number of useful datasets. One such data set is h02.
Use the help() function to get a decription of this data. Try
Now let us create a nice plot of the h02 data

Let us leave it there for now!
LS0tDQp0aXRsZTogIlNob3J0IEludHJvZHVjdGlvbiB0byBSIg0Kc3VidGl0bGU6ICdUdXRvcmlhbCBvbiBSIFN0dWRpbycNCiMgbG9nbzogLi4vaW1hZ2VzL3JzdHVkaW8tc3RhcnQucG5nDQphdXRob3I6IEFwcGxpZWQgRWNvbm9taWMgRm9yZWNhc3RpbmcNCiNpbnN0aXR1dGU6IHwNCiMgIHwgRGVwYXJ0bWVudCBvZiBBZ3JpY3VsdHVyYWwgJiBBcHBsaWVkIEVjb25vbWljcw0KIyAgfCBWaXJnaW5pYSBUZWNoDQojIGRhdGU6ICIxLzE4LzIwMjEiDQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOg0KICAgIHRoZW1lOiBqb3VybmFsDQogICAgaGlnaGxpZ2h0OiBweWdtZW50cw0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiAzDQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICBmb250dGhlbWU6ICJzZXJpZiINCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgZWNobz1GQUxTRSwgaW5jbHVkZT1GQUxTRSwgd2FybmluZz1GQUxTRX0gDQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFKQ0KcmVxdWlyZShmcHAyKQ0KcmVxdWlyZShxdWFudG1vZCkNCnJlcXVpcmUoYXN0c2EpDQp0aGVtZV9zZXQodGhlbWVfYncoKSkNCmBgYA0KDQojIFBhcnQgSTogYFJgIEludHJvZHVjdGlvbg0KDQojIyBXaGF0IGlzIGBSYD8NCg0KYFJgIGlzIGEgKipwcm9ncmFtbWluZyBsYW5ndWFnZSoqIHVzZWQgZm9yIHN0YXRpc3RpY2FsIGFuYWx5c2lzIGFuZCBncmFwaGljcy4gSXQgaXMgYmFzZWQgb24gUy1wbHVzLCB3aGljaCBpdHNlbGYgd2FzIGJhc2VkIG9uIFMsIGEgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2Ugb3JpZ2luYWxseSBkZXZlbG9wZWQgYnkgQVQmVC4gDQoNCiMjIFdoeSBgUmA/DQoNCi0gT3BlbiBzb3VyY2UsIGNyb3NzLXBsYXRmb3JtLCBhbmQgKipmcmVlKioNCi0gR3JlYXQgZm9yIHJlcHJvZHVjaWJpbGl0eQ0KLSBJbnRlcmRpc2NpcGxpbmFyeSBhbmQgZXh0ZW5zaWJsZQ0KLSBUb25zIG9mIGxlYXJuaW5nIHJlc291cmNlcw0KLSBXb3JrcyBvbiBkYXRhIG9mIGFsbCBzaGFwZXMgYW5kIHNpemVzDQotIFByb2R1Y2VzIGhpZ2gtcXVhbGl0eSBncmFwaGljcw0KLSBMYXJnZSBhbmQgd2VsY29taW5nIGNvbW11bml0eQ0KDQoNCiMjIGBSYDogT2JqZWN0LU9yaWVudGVkIFByb2dyYW1taW5nDQoNClVubGlrZSBtYW55IG90aGVyIHN0YXRpc3RpY2FsIHNvZnR3YXJlIHN1Y2ggYXMgU0FTIGFuZCBTUFNTLCBgUmAgd2lsbCBub3Qgc3BpdCBvdXQgYSBtb3VudGFpbiBvZiBvdXRwdXQgb24gdGhlIHNjcmVlbi4NCg0KSW5zdGVhZCwgYFJgIHJldHVybnMgYW4gKipvYmplY3QqKiBjb250YWluaW5nIGFsbCB0aGUgcmVzdWx0cy4gWW91LCBhcyBhbiB1c2VyLCBoYXZlIHRoZSBmbGV4aWJpbGl0eSB0byBjaG9vc2Ugd2hpY2ggcmVzdWx0IHRvIGJlIGV4dHJhY3RlZCBvciByZXBvcnRlZC4NCg0KDQojIyBgUmA6IEZ1bmN0aW9uYWwgUHJvZ3JhbW1pbmcNCg0KVGhpcyBmZWF0dXJlIGFsbG93cyB1cyB0byB3cml0ZSBmYXN0ZXIgeWV0IG1vcmUgY29tcGFjdCBjb2RlLiBGb3IgZXhhbXBsZSwgYSBjb21tb24gdGhlbWUgaW4gYFJgIHByb2dyYW1taW5nIGlzICoqYXZvaWRhbmNlIG9mIGV4cGxpY2l0IGl0ZXJhdGlvbioqLiBVbmxpa2UgbWFueSBvdGhlciBzdGF0aXN0aWNhbCBzb2Z0d2FyZXMsIGV4cGxpY2l0IGxvb3BzIGFyZSBkaXNjb3VyYWdlZC4NCg0KDQpJbnN0ZWFkLCBgUmAgcHJvdmlkZXMgc29tZSBmdW5jdGlvbnMgdGhhdCBjb3VsZCBhbGxvdyB1cyB0byBleHByZXNzIGl0ZXJhdGl2ZSBiZWhhdmlvciBpbXBsaWNpdGx5Lg0KDQoNCiMjIGBSYDogUG9seW1vcnBoaWMNCg0KYFJgIGlzIGFsc28gKnBvbHltb3JwaGljKiwgd2hpY2ggbWVhbnMgdGhhdCBhIHNpbmdsZSBmdW5jdGlvbiBjYW4gYmUgYXBwbGllZCB0byBkaWZmZXJlbnQgdHlwZXMgb2YgaW5wdXRzIChtdWNoIG1vcmUgdXNlciBmcmllbmRseSkuDQoNClN1Y2ggYSBmdW5jdGlvbiBpcyBjYWxsZWQgYSAqZ2VuZXJpYyBmdW5jdGlvbiogKElmIHlvdSBhcmUgYSBDKysgcHJvZ3JhbW1lciwgeW91IGhhdmUgc2VlbiBhIHNpbWlsYXIgY29uY2VwdCBpbiAqdmlydHVhbCBmdW5jdGlvbnMqKS4NCg0KIyMgUG9seW1vcnBoaWMgLSBFeGFtcGxlDQoNCkxldHMgbG9vayBhdCBvbmUgZXhhbXBsZSBgcGxvdCgpYA0KDQoxLiBQbG90IGEgdmVjdG9yIG9mIG51bWJlcnMNCjIuIFBsb3Qgc29tZSBtb2RlbCByZXN1bHRzDQoNCk5vIG1hdHRlciB3aGljaCBwdXJwb3NlLCB3ZSB1c2UgdGhlIHNhbWUgZnVuY3Rpb24uDQoNCmBgYHtyLCBlY2hvPVRSVUUsIGZpZy5oZWlnaHQ9NH0NCmRhdGE8LWMoMSwyLDMsNCkNCnBsb3QoZGF0YSkNCmBgYA0KDQoNCmBgYHtyLCBlY2hvPVRSVUUsIGZpZy5zaG93PSAiaG9sZCIsIGZpZy5oZWlnaHQ9NX0NCiMgUmVncmVzc2lvbiBBbmFseXNpcw0KcGFyKG1mcm93PWMoMiwyKSxtYXI9YygyLDQsMiwyKSkNCnJlc3VsdHM8LWxtKHNwZWVkIH4gZGlzdCxkYXRhPWNhcnMpDQpwbG90KHJlc3VsdHMpDQpgYGANCg0KDQojIyBXaHkgUiBTdHVkaW8/DQoNCi0gYFJgIEludGVyZmFjZSBpcyAqKnVnbHkqKiENCg0KDQotIE1hbnkgc3R1ZGVudHMgaW4gdGhpcyBjbGFzcyBhcmUgbXVjaCBtb3JlIGZhbWlsaWFyIHdpdGggV2luZG93cyBvcGVyYXRpb24gc3lzdGVtIGFuZCBoYXZlIG5ldmVyIGJlZW4gZXhwb3NlZCBwcm9ncmFtbWluZyBiZWZvcmUsIHNvIHdlIHdpbGwgdXNlIFIgc3R1ZGlvLCBvbmUgb2YgdGhlIGZyZWUgR3JhcGhpY2FsIFVzZXIgSW50ZXJmYWNlcyAoR1VJcykgdGhhdCBoYXZlIGJlZW4gZGV2ZWxvcGVkIGZvciBgUmAuDQoNCi0gUiBzdHVkaW8gc2hvdWxkIHJlYWxseSBiZSBjb25zaWRlcmVkIGFzICppbnRlZ3JhdGVkIGRldmVsb3BtZW50IGVudmlyb25tZW50cyogKElERXMpLCBzaW5jZSBpdCBpcyBhaW1lZCBtb3JlIHRvd2FyZCBwcm9ncmFtbWluZy4NCg0KLSBFYXN5IHB1Ymxpc2hpbmcgb2YgcmVwcm9kdWNpYmxlIGRvY3VtZW50cyBzdWNoIGFzIHJlcG9ydHMsIGludGVyYWN0aXZlIHZpc3VhbGl6YXRpb25zLCBwcmVzZW50YXRpb25zLCBhbmQgd2Vic2l0ZXMuDQoNCiMjIFIgU3R1ZGlvOiBBIHNob3J0IHRvdXINCg0KKipJbml0aWFsIFN0YXJ0KioNCg0KV2hlbiB5b3UgZmlyc3QgKGxpa2UgdmVyeSBmaXJzdCB0aW1lKSBvcGVuIFIgc3R1ZGlvIHlvdSB3aWxsIHNlZSB0aHJlZSBwYW5lbHMuDQoNCg0KIVtdKC4uL2ltYWdlcy9yc3R1ZGlvLXN0YXJ0LnBuZykNCg0KLS0tDQoNCioqQ29uc29sZSoqDQoNCiFbXSguLi9pbWFnZXMvcnN0dWRpby1jb25zb2xlLnBuZyl7c2NhbGU9MzAlfQ0KDQoxLiBFdmVyeSB0aW1lIHlvdSBsYXVuY2ggUlN0dWRpbywgaXQgd2lsbCBoYXZlIHRoZSBzYW1lIHRleHQgYXQgdGhlIHRvcCBvZiB0aGUgY29uc29sZSB0ZWxsaW5nIHlvdSB0aGUgdmVyc2lvbiBvZiBSIHRoYXQgeW91J3JlIHJ1bm5pbmcuDQoyLiBCZWxvdyB0aGF0IGluZm9ybWF0aW9uIGlzIHRoZSBwcm9tcHQsIGA+YCAuIEFzIGl0cyBuYW1lIHN1Z2dlc3RzLCB0aGlzIHByb21wdCBpcyByZWFsbHkgYSByZXF1ZXN0LCBhIHJlcXVlc3QgZm9yIGEgY29tbWFuZC4NCjMuIEluaXRpYWxseSwgaW50ZXJhY3Rpbmcgd2l0aCBSIGlzIGFsbCBhYm91dCB0eXBpbmcgY29tbWFuZHMgYW5kIGludGVycHJldGluZyB0aGUgb3V0cHV0Lg0KNC4gVGhlc2UgY29tbWFuZHMgYW5kIHRoZWlyIHN5bnRheCBoYXZlIGV2b2x2ZWQgb3ZlciBkZWNhZGVzIChsaXRlcmFsbHkpIGFuZCBub3cgcHJvdmlkZSB3aGF0IG1hbnkgdXNlcnMgZmVlbCBpcyBhIGZhaXJseSBuYXR1cmFsIHdheSB0byBhY2Nlc3MgZGF0YSBhbmQgb3JnYW5pemUsIGRlc2NyaWJlLCBhbmQgaW52b2tlIHN0YXRpc3RpY2FsIGNvbXB1dGF0aW9ucy4NCg0KDQpUaGUgY29uc29sZSBpcyB3aGVyZSB5b3UgdHlwZSBjb21tYW5kcyBhbmQgaGF2ZSB0aGVtIGltbWVkaWF0ZWx5IHBlcmZvcm1lZC4NCg0KLS0tDQoNCioqRW52aXJvbm1lbnQqKg0KDQpUaGUgcGFuZWwgaW4gdGhlIHVwcGVyIHJpZ2h0IGNvbnRhaW5zIHlvdXIgd29ya3NwYWNlIChha2EgRW52aXJvbm1lbnQpDQoNCiFbXSguLi9pbWFnZXMvcnN0dWRpby1lbnYucG5nKQ0KDQoxLiBUaGlzIHNob3dzIHlvdSBhIGxpc3Qgb2Ygb2JqZWN0cy92YXJpYWJsZXMgdGhhdCBSIGhhcyBzYXZlZC4NCjIuIEZvciBleGFtcGxlIGhlcmUgYSB2YWx1ZSBvZiBgM2AgaGFzIGJlZW4gYXNzaWduZWQgdG8gdGhlIG9iamVjdCBgYWAuDQoNCi0tLQ0KDQoqKkhpc3RvcnkqKg0KDQpVcCBoZXJlIHRoZXJlIGlzIGFuIGFkZGl0aW9uYWwgdGFiIHRvIHNlZSB0aGUgaGlzdG9yeSBvZiB0aGUgY29tbWFuZHMgdGhhdCB5b3UndmUgcHJldmlvdXNseSBlbnRlcmVkLg0KDQoNCg0KIVtdKC4uL2ltYWdlcy9yc3R1ZGlvLWhpc3RvcnkucG5nKQ0KDQoNCi0tLQ0KDQoqKkZpbGVzKioNCg0KVGhlIGZpbGVzIHRhYiBhbGxvd3MgeW91IHRvIG9wZW4gY29kZS9zY3JpcHQgZmlsZXMgd2l0aGluIFIgc3R1ZGlvLg0KDQoNCiFbXSguLi9pbWFnZXMvcnN0dWRpby1maWxlcy5wbmcpDQoNCi0tLQ0KDQoqKlBsb3RzKioNCg0KQW55IHBsb3RzIHRoYXQgeW91IGdlbmVyYXRlIHdpbGwgc2hvdyB1cCBpbiB0aGUgcGFuZWwgaW4gdGhlIGxvd2VyIHJpZ2h0IGNvcm5lci4NCg0KDQohW10oLi4vaW1hZ2VzL3JzdHVkaW8tcGxvdC5wbmcpDQoNCi0tLQ0KDQoqKkhlbHAqKg0KDQpUbyBjaGVjayB0aGUgc3ludGF4IG9mIGFueSBmdW5jdGlvbiBpbiBSLCB0eXBlID8gaW4gZnJvbnQgb2YgdGhlIGZ1bmN0aW9uIG5hbWUgdG8gcHVsbCB1cCB0aGUgaGVscCBmaWxlLg0KDQoNCiFbXSguLi9pbWFnZXMvcnN0dWRpby1oZWxwLnBuZykNCg0KRm9yIGV4YW1wbGUgaGVyZSBJIHR5cGVkIGA/bWVhbmAgdG8gZ2V0IHRoZSBoZWxwIGZpbGUgZm9yIHRoZSBtZWFuIGZ1bmN0aW9uLiBUaGUgaGVscCBmaWxlcyBhcmUgbm90IGFsd2F5cyB0aGUgbW9zdCB1c2VmdWwgYnV0IGFyZSB1c3VhbGx5IGEgZ29vZCBwbGFjZSB0byBzdGFydC4NCg0KLS0tDQoNCioqU2NyaXB0IEZpbGUqKiBUaGUgdG9wIGxlZnQgaXMgeW91ciBlZGl0b3Igd2luZG93LCB3aGVyZSB5b3Ugd3JpdGUgY29kZSBvciBzY3JpcHQsIHRoZSBjb25zb2xlIGlzIG5vdyBhdCB0aGUgYm90dG9tLiAqKkkgdXN1YWxseSBjaGFuZ2UgaXQqKg0KDQohW10oLi4vaW1hZ2VzL3JzdHVkaW8tY2hhbmdlZC5wbmcpDQoNClRoZSBwaWN0dXJlIGFib3ZlIGlsbHVzdHJhdGVzIG15IHByZWZlcnJlZCBzdHlsZSBpbiBSIFN0dWRpby4NCg0KDQojIyBSIFNjcmlwdA0KDQpNb3N0IG9mIGBSYCB1c2VycyB0eXBpY2FsbHkgc3VibWl0IGNvbW1hbmRzIHRvIGBSYCBieSB0eXBpbmcgZWl0aGVyIGluIGNvbnNvbGUgb3IgZWRpdG9yIHBhbmVsLCByYXRoZXIgdGhhbiBjbGlja2luZyBhIG1vdXNlIGluIGEgR3JhcGhpY2FsIFVzZXIgSW50ZXJmYWNlIChHVUkpLg0KDQpJbiB0aGlzIGNsYXNzLCB3ZSB3aWxsIG1ha2UgZXh0ZW5zaXZlIHVzZSBvZiBzY3JpcHRzLiBBICoqU2NyaXB0KiogaXMgbm90aGluZyBidXQgKiphIGNvbGxlY3Rpb24gb2YgY29tbWFuZHMgYW5kIHByb2NlZHVyZXMgdGhhdCB0aGUgY29kZXIgcGVyZm9ybWVkIHRvIGdldCB0byB0aGVpciByZXN1bHRzIGFuZCBjb25jbHVzaW9ucy4qKi4NCg0KVGhlcmUgYXJlIGF0IGxlYXN0IHR3byBhZHZhbnRhZ2VzIG9mIGRvaW5nIHNvOg0KDQoxLiBBcyBleHBsYWluZWQgZWFybGllciwgdGhpcyBhbGxvd3MgdXMgdG8gcnVuIGEgYnVuY2ggb2YgcmVzdWx0cyBhbHRvZ2V0aGVyIGJ5IHB1dHRpbmcgYSBjb2xsZWN0aW9uIG9mIGNvbW1hbmRzIGluIGEgZmlsZS4NCjIuIEl0IGlzIGFsc28gYSBsb3QgbW9yZSB0cmFuc3BhcmVudCBhbmQgc3RyYWlnaHRmb3J3YXJkIHRvICoqc2hhcmUqKiBhbmQgKipyZXBsaWNhdGUqKiB3aGF0IHlvdSBoYXZlIGRvbmUuDQoNCjxwIGFsaWduPSJjZW50ZXIiPiA8Yj4gVGhpcyB3aWxsIGFsd2F5cyBiZSBvdXIgYXBwcm9hY2ggaW4gdGhpcyBjbGFzcyEhISA8L2I+IDwvcD4NCg0KLS0tDQoNCiMjIEV4ZXJjaXNlDQoNCiMjIyAqKlRhc2sgMToqKiBDcmVhdGUgYSBzY3JpcHQgZmlsZQ0KDQoxLiBPcGVuIFIgU3R1ZGlvIGFuZCBnbyB0byBgRmlsZSA+IE5ldyA+IFIgU2NyaXB0YC4NCg0KVGhpcyB3aWxsIG9wZW4gYSBibGFuayB0ZXh0IGRvY3VtZW50Lg0KDQotIFR3byBhbHRlcm5hdGl2ZSB3YXlzIGFyZTogDQogIC0gKipDVFJMICsgU0hJRlQgKyBOKiogb3INCiAgLSAqKnByZXNzIHRoZSBidXR0b24gbWFya2VkICIrIiwganVzdCBiZWxvdyBGaWxlLCBhbmQgc2VsZWN0IFIgU2NyaXB0KioNCg0KMi4gSW4gdGhlIGRvY3VtZW50LCB0eXBlDQoNCg0KYGBge3IsIGV2YWw9RkFMU0V9DQp4ID0gNSAgIyBBc3NpZ24gdGhlIHZhcmlhYmxlIHggYSB2YWx1ZSBvZiA1DQp4ID09IDUgICMgRG9lcyB4ID0gNT8gTm90aWNlIHRoZSBkb3VibGUgPT0NCmBgYA0KDQotIEhpZ2hsaWdodCBib3RoIGxpbmVzIG9mIGNvZGUgYW5kIGNsaWNrIHRoZSBidXR0b24gbWFya2VkICJSdW4iLiBJZiBldmVyeXRoaW5nIGlzIHdvcmtpbmcgY29ycmVjdGx5LCB0aGUgY29uc29sZSBzaG91bGQgZGlzcGxheSBUUlVFLg0KDQotIE9SLCBwcmVzc2luZyAqKkNUUkwgKyBFTlRFUioqICBvciAqKkNPTU1BTkQgKyBSRVRVUk4qKiBkZXBlbmRpbmcgb24gd2hldGhlciB5b3UncmUgcnVubmluZyBNYWMgT1NYLCBMaW51eCBvciBXaW5kb3dzLg0KDQozLiBHbyB0byAiRmlsZSA+IFNhdmUgQXMiLCBhbmQgY2hvb3NlIGEgZmlsZSBuYW1lLg0KDQotLS0NCg0KIyBQYXJ0IElJOiBXb3JraW5nIHdpdGggU2NyaXB0cw0KDQojIyBDb21tZW50cw0KDQpXaGVuZXZlciBwb3NzaWJsZSwgdXNlIGNvbW1lbnRzISBBbnl0aGluZyBmb2xsb3dpbmcgdGhlIHN5bWJvbCBgI2AgaW4gYW4gKipSIFNjcmlwdCoqIHdpbGwgbm90IGJlIHJ1biBpbiBSLg0KDQpDb21tZW50cyBhcmUgbm90ZXMgd2UgbGVhdmUgb3Vyc2VsdmVzIHNvIHdlIGtub3c6DQoNCiAgLSBleGFjdGx5IHdobyB3cm90ZSB0aGUgY29kZSAoaW1wb3J0YW50IGluIGNvbXBhbmllcyB3aGVyZSBtYW55IHBlb3BsZSBtYXkgd29yayBvbiBhIHByb2plY3QpDQogIC0gdGhlIHB1cnBvc2Ugb2YgdGhlIGNvZGUhDQogIC0gd2hhdCBvdXIgdGhvdWdodCBwcm9jZXNzIHdhcyBhdCBhIHBhcnRpY3VsYXIgbGluZSBvZiBjb2RlLg0KDQpJIHByb21pc2UgdGhhdCB0aGlzIHdpbGwgYmVjb21lIHVzZWZ1bCB3aGVuIHlvdSBjb21lIGJhY2sgdG8geW91ciBjb2RlIGFmdGVyIGFuIGV4dGVuZGVkIHRpbWUuIEkgY2Fubm90IHRlbGwgeW91IHRoZSBudW1iZXIgb2YgdGltZXMgSSBoYXZlIGhhZCBhIG1vbWVudCBvZiBwdXJlIGdlbml1cyB3aGlsZSBjb2RpbmcgYW5kIEkgc3BlbmQgaG91cnMgb24gYSBkaWZmZXJlbnQgZGF5IHRyeWluZyB0byB1bmRlcnN0YW5kIHdoeSBJIGNvZGVkIGl0IGxpa2UgdGhhdCBvciB3aGF0IEkgYWN0dWFsbHkgZGlkLg0KDQotLS0NCg0KRm9yIGV4YW1wbGUsIGJlbG93IGlzIHRoZSB0eXBlIG9mIGNvbW1lbnRzIHRoYXQgSSBhbHdheXMgaW5jbHVkZSBpbiBteSBwcm9ncmFtcw0KYGBgDQojIFByb2plY3Q6ICdUdXRvcmlhbCBvbiBSIFN0dWRpbyBJSScNCiMgQXV0aG9yOiAgU2hhbWFyIFN0ZXdhcnQNCiMgVGhpcyBwcm9ncmFtIGlsbHVzdHJhdGVzIHNvbWUgYmFzaWMgcHJvZ3JhbW1pbmcgcGhpbG9zb3BoeQ0KIyBhbmQgUiBvcGVyYXRpb25zDQpgYGANCg0KWW91IGNhbiBhbHNvIHVuZGVyc3RhbmQgdGhlIGZvbGxvd2luZyBjb2RlIHdpdGhvdXQgZXZlbiBrbm93aW5nIHdoYXQgZXhhY3RseSBlYWNoIGxpbmUgb2YgY29tbWFuZCBkb2VzIGJlY2F1c2UgSSB0ZWxsIHlvdSB3aGF0IHRoZXkgYXJlIQ0KDQpgYGB7cn0NCiMgU2V0IHNlZWQgbnVtYmVyIHNvIHRoYXQgYWxsIHRoZSByZXN1bHRzIGJhc2VkIG9uIHJhbmRvbSBzYW1wbGVzDQojIGFyZSByZXByb2R1Y2libGUuDQogIHNldC5zZWVkKDEyMzQ1KQ0KIyBUaGVuIGNyZWF0ZSBhIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIHJhbmRvbSB2YXJpYWJsZSwgeCwgd2l0aCA1MDANCiMgb2JzZXJ2YXRpb25zLg0KICB4IDwtIHJub3JtKDUwMCkNCiMgTm90aWNlICI8LSIgaXMgdGhlIHVuaXZlcnNhbCBhc3NpZ25tZW50IG9wZXJhdG9yIGluIFIgKEkgcHJlZmVyIHRoaXMgdG8gIj0iKQ0KYGBgDQoNCi0tLQ0KDQojIyBFeGVyY2lzZQ0KIyMjICoqVGFzayAyOioqDQoNCkF0IHRoZSB0b3Agb2YgdGhlIHByZXZpb3VzIHNjcmlwdCAoVGFzayAxKSwgIHdyaXRlIGFkZCBhbmQgZXhwYW5kIG9uIHRoZSBmb2xsb3dpbmcgY29tbWVudHM6DQoNCiAgMS4gVGhlIHByb2plY3QNCiAgMi4gVGhlIGF1dGhvcg0KICAzLiBUaGUgcHVycG9zZSBvZiB0aGlzIHByb2dyYW0NCg0KKipGb2xsb3cgdGhlIGV4YW1wbGUgZ2l2ZW4gYWJvdmUuKioNCg0KLS0tDQoNCiMjIFIgQmFzaWNzDQoNCioqQXJpdGhtZXRpYyoqDQoNCmBgYHtyfQ0KDQogIDEgKyAxICNhZGQgbnVtYmVycw0KDQogIDggLSA0ICNzdWJ0cmFjdCB0aGVtDQoNCiAgMTMvMiAjZGl2aWRlDQoNCiAgNCpwaSAjbXVsdGlwbHkgKFBpIGlzIGEgYnVpbHQgaW4gZnVuY3Rpb24gaW4gUikNCg0KICAyXjEwICNleHBvbmVudGlhdGUNCmBgYA0KDQotLS0NCg0KIyMgTG9naWNhbCBDb21wYXJpc29uDQoNCkxvZ2ljYWwgYXJndW1lbnRzIHdpbGwgcmVzdWx0IGluIGEgdmFsdWUgb2YgYFRSVUVgIG9yIGBGQUxTRWAuDQoNCg0KYGBge3J9DQogIDMgPCA0DQogIDMgPiA0DQogIDMgPT0gNA0KICAzICE9IDQNCiAgMTAgLSA2ID09IDQNCg0KICAjIE5vdGljZSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHNpbmdsZSBhbmQgZG91YmxlIGVxdWFsIHNpZ25zDQpgYGANCg0KTm93IHRyeSBgMyA9IDRgLiBXaGF0IGlzIHRoZSByZXN1bHQgaGVyZT8NCg0KIyMgU3RyaW5ncyAodGV4dCkNCg0KYGBge3J9DQojUiBkZWxpbWl0cyBzdHJpbmdzIHdpdGggRUlUSEVSIGRvdWJsZSBvciBzaW5nbGUgcXVvdGVzLg0KI1RoZXJlIGlzIG9ubHkgYSB2ZXJ5IG1pbmltYWwgZGlmZmVyZW5jZQ0KDQptZXNzYWdlMSA8LSAnTGV0IHVzIGdldCB0byBjb2RpbmchJw0KbWVzc2FnZTIgPC0gICJQbGVhc2UgZ2V0IHRvIGNvZGluZyEiDQpwcmludChtZXNzYWdlMSkNCnByaW50KG1lc3NhZ2UyKQ0KYGBgDQoNCldlIGNhbiBhbHNvIHByaW50IHRoZSByZXN1bHQocykgc3RvcmVkIGluIG91ciB2YXJpYWJsZXMgYnkgc2ltcGx5IHJ1bm5pbmcgdGhlIHJ1bm5pbmcgdGhlIHZhcmlhYmxlIG5hbWUgaW5zdGVhZCBvZiBgcHJpbnQoKWAuDQoNCmBgYHtyfQ0KbWVzc2FnZTENCmBgYA0KDQoNCiMjIFZhcmlhYmxlcw0KDQotIHZhcmlhYmxlIGFyZSB1c2VkIHRvIHN0b3JlIHZhbHVlcyBhbmQgcmVzdWx0cy4gQXNzaWdubWVudCB0byBhIHZhcmlhYmxlIGhhcHBlbnMgZnJvbSByaWdodCB0byBsZWZ0IC0gdGhlIHZhbHVlIG9uIHRoZSByaWdodCBzaWRlIGdldHMgYXNzaWduZWQgdG8gdGhlIG5hbWUgb24gdGhlIGxlZnQgc2lkZS4gWW91IGNhbiB1c2UgbmVhcmx5IGFueXRoaW5nIGFzIGEgdmFyaWFibGUgbmFtZSBpbiBSLiBUaGUgb25seSBydWxlcyBhcmU6DQoNCjEuICIuIiBhbmQgIl8iIGFyZSBPSyB0byBiZSBhZGRlZCB0byB2YXJpYWJsZSBuYW1lcywgYnV0IG5vIG90aGVyIHN5bWJvbHMuDQoNCjIuIFlvdXIgdmFyaWFibGUgbmFtZSBtdXN0IG5vdCBzdGFydCB3aXRoIGEgbnVtYmVyIG9yICJfIiAoYDJzcXVhcmVkYCBhbmQgIGBfb25lYCBhcmUgaWxsZWdhbCkuDQoNCi0gQSBub3RlIGZvciB0aG9zZSBvZiB5b3Ugd2hvIGhhdmUgcHJvZ3JhbW1pbmcgZXhwZXJpZW5jZTogd2hpbGUgUiBzdXBwb3J0cyBvYmplY3Qtb3JpZW50ZWQgcHJvZ3JhbW1pbmcsIHBlcmlvZHMgIi4iIGRvIG5vdCBoYXZlIGEgc3BlY2lhbCBtZWFuaW5nIGluIHRoZSBsYW5ndWFnZS4gRm9yIGhpc3RvcmljYWwgcmVhc29ucywgUiBwcm9ncmFtbWVycyBvZnRlbiB1c2UgcGVyaW9kcyBpbiBwbGFjZSBvZiB1bmRlcnNjb3JlcyBpbiB2YXJpYWJsZSBuYW1lcywgYnV0IGVpdGhlciB3b3Jrcy4gSnVzdCBiZSBjb25zaXN0ZW50IHRvIGtlZXAgeW91ciBjb2RlIHJlYWRhYmxlLg0KDQotIGBSYCBpcyBjYXNlIHNlbnNpdGl2ZS4gQ2FwaXRhbGl6YXRpb24gb2YgdmFyaWFibGUgbmFtZXMgbWF0dGVyLg0KDQpgYGB7cn0NCiAgICB4IDwtIDQyDQogICAgeCAvIDINCg0KICAgICMgcmVkZWZpbmUgeA0KICAgIHggPC0geCArIDMNCiAgICB4DQoNCiAgICAjaWYgd2UgYXNzaWduIHNvbWV0aGluZyBlbHNlIHRvIHgsIHRoZSBvbGQgdmFsdWUgaXMgZGVsZXRlZA0KICAgIHggPC0gIkhva2llcyEiDQogICAgeA0KDQogICAgZm9vIDwtIDMNCiAgICBiYXIgPC0gNQ0KICAgIGZvby5iYXIgPC0gZm9vICsgYmFyDQogICAgZm9vLmJhcg0KYGBgDQoNCg0KLS0tDQoNCiMjIEV4ZXJjaXNlDQoNCiMjIyAqKlRhc2sgMzoqKg0KDQoxLiBDcmVhdGUgYSB2YXJpYWJsZSBjYWxsZWQgYGVudHJ5YCB0aGF0IHN0b3JlcyB0aGUgeWVhciB5b3Ugc3RhcnRlZCBhdCBWaXJnaW5pYSBUZWNoLg0KMi4gU3RvcmUgdGhlIGN1cnJlbnQgeWVhciB0byBhIHZhcmlhYmxlIGNhbGxlZCBgY3VycmVudF90YC4NCjIuIENvbXB1dGUgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBgY3VycmVudF90YCBhbmQgYGVudHJ5YC4gU3RvcmUgdGhpcyBhcyBgZGlmZnNgLg0KMy4gU3RvcmUgeW91ciBiaXJ0aCB5ZWFyIGFzIGBteV95ZWFyYC4gTm93IGNvbXB1dGUgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBgY3VycmVudF90YCBhbmQgYG15X3llYXJgLiBBc3NpZ24gdGhlIHJlc3VsdHMgdG8gYG15X2RpZmZzYC4NCjUuIFVzZSB0aGlzIGluZm9ybWF0aW9uIHRvIGNvbXB1dGUgdGhlIHBlcmNlbnRhZ2Ugb2YgeW91ciBsaWZlIGhhdmUgc3BlbnQgYXQgdGhpcyB1bml2ZXJzaXR5LiBCZSBzdXJlIHRvIHVzZSBicmFja2V0cyBpZiB5b3UgbmVlZCB0aGVtLg0KNi4gQXNzaWduIHRoaXMgcmVzdWx0IHRvIGEgdmFyaWFibGUgb2YgeW91ciBjaG9vc2luZy4NCg0KLS0tDQoNCiMjIENsZWFyaW5nIHRoZSBtZW1vcnkNCg0KVG8gcmVtb3ZlIGFsbCB2YXJpYWJsZXMgaW4gbWVtb3J5Og0KDQpgYGB7cn0NCiMgICAgbHMoKSAjIExpc3Qgb2YgYWxsIHZhcmlhYmxlcyBpbiBtZW1vcnkNCiAgICBybShsaXN0PWxzKCkpDQpgYGANCg0KLSBJIHVzdWFsbHkgcGxhY2UgdGhpcyBhdCB0aGUgYmVnaW5uaW5nIG9mIG15IGBSYCBzY3JpcHQgKGp1c3QgYWZ0ZXIgdGhlIGRvY3VtZW50IGRldGFpbHMpLg0KDQoNCiMgUGFydCBJSUk6IGBSYCBEYXRhIHR5cGVzDQoNCiMjIERhdGEgdHlwZXMgaW4gYFJgDQoNCllvdSBoYXZlIG9ic2VydmVkIGEgZmV3IG9mIHRoZSBkaWZmZXJlbnQgZGF0YSB0eXBlcyBpbiB0aGUgZWFybGllciBzZWN0aW9ucy4gSGVyZSwgd2Ugd2lsbCBmb3JtYWxseSBkaXNjdXNzIHRoZW0uIFNvbWUgb2YgdGhlIG1vc3QgYmFzaWMgZGF0YSB0eXBlcyB3ZSB3aWxsIGNvdmVyIGFyZToNCg0KICAxLiAqKkRlY2ltYWwgdmFsdWVzKiogbGlrZSA0LjUgYXJlIGNhbGxlZCBudW1lcmljcy4NCiAgMi4gKipOYXR1cmFsIG51bWJlcnMqKiAgbGlrZSA0IGFyZSBjYWxsZWQgaW50ZWdlcnMuIEludGVnZXJzIGFyZSBhbHNvIG51bWVyaWNzLg0KICAzLiAqKkJvb2xlYW4gdmFsdWVzKiogIChUUlVFIG9yIEZBTFNFKSBhcmUgYWxzbyBjYWxsZWQgbG9naWNhbC4NCiAgNC4gKipUZXh0KiogIChvciBzdHJpbmcpIHZhbHVlcyBhcmUgY2FsbGVkIGNoYXJhY3RlcnMuDQoNCg0KWW91IGNhbiBjaGVjayB0aGUgdHlwZSBvZiBkYXRhIGJ5IHVzaW5nIGBjbGFzcygpYC4NCg0KYGBge3J9DQogIHggPC0gIkx5cmljcyB0byBWaXJnaW5pYSBUZWNoIEZpZ2h0IFNvbmchIg0KICBjbGFzcyh4KQ0KDQogIHgyIDwtIGMoIlRSVUUiLCAiRkFMU0UiKQ0KICB4MiA8LSBhcy5sb2dpY2FsKHgyKSAjRGVjbGFyZSB0aGUgZGF0YSB0eXBlDQogIHgyDQogIGNsYXNzKHgyKQ0KDQogIHggPC0gMToyMA0KICB4ICUlIDQgI3ggbW9kIDQNCiAgeCAlJSA0ID09IDANCiAgY2xhc3MoeCAlJSA0ID09IDApDQpgYGANCg0KDQojIyBWZWN0b3JzDQoNCg0KQSB2ZWN0b3IgaXMgdGhlIG1vc3QgY29tbW9uIGFuZCBiYXNpYyBkYXRhIHR5cGUgaW4gUiwgYW5kIGlzIHByZXR0eSBtdWNoIHRoZSB3b3JraG9yc2Ugb2YgUi4gQSB2ZWN0b3IgaXMgY2hhcmFjdGVyaXplZCBieSBhIHNlcmllcyBvZiB2YWx1ZXMsIHdoaWNoIGNhbiBiZSBlaXRoZXIgbnVtYmVycyBvciBjaGFyYWN0ZXJzLiBXZSBjYW4gYXNzaWduIGEgc2VyaWVzIG9mIHZhbHVlcyB0byBhIHZlY3RvciB1c2luZyB0aGUgYGMoKWAgZnVuY3Rpb24uDQoNCkluIHNob3J0LCB2ZWN0b3JzIGFyZSBtb3N0IHVzZWZ1bCB3aGVuIHdlIGhhdmUgYSBjb2xsZWN0aW9uIG9mIGRhdGEgcG9pbnRzLg0KDQpIZXJlIGBjKClgIHN0YW5kcyBmb3IgKipjb25jYXRlbmF0ZSoqIG9yICoqY29tYmluZSoqLg0KDQoNCmBgYHtyfQ0KKHYgPC0gYygxLCAyLCAzLCA0KSkNCih2IDwtIDE6NCkNCih2IDwtIHNlcShmcm9tID0gMCwgdG8gPSAwLjUsIGJ5ID0gMC4xKSkNCg0KI0EgdmVjdG9yIGNhbiBhbHNvIGNvbnRhaW4gY2hhcmFjdGVyczoNCih2X2NvbG9ycyA8LSBjKCJibHVlIiwgInllbGxvdyIsICJsaWdodCBncmVlbiIpCSkNCg0KYGBgDQoNCjxiPiBOb3RpY2UgdGhhdCBieSBlbmNhc2luZyB0aGUgYmVnaW5uaW5nIGFuZCBlbmQgb2YgdGhlIGFzc2lnbm1lbnQgbGluZXMgaW4gcGFyZW50aGVzZXMsIHdlIGltbWVkaWF0ZWx5IHByaW50IHRoZSBzdG9yZWQgdmFsdWVzLiA8L2I+DQoNCiMjIFN1YnNldHRpbmcgdmVjdG9ycyAoSW5kZXhpbmcvcmVhc3NpZ25pbmcgZWxlbWVudHMpDQoNCldlIGFyZSBhYmxlIHRvIGluZGV4IChjb2xsZWN0IHN1YnNldHMgb2Ygb3VyIHZhcmlhYmxlcykgYnkgdXNpbmcgc3F1YXJlZCBicmFja2V0cy4gVW5saWtlIHB5dGhvbiwgZm9yIGV4YW1wbGUsIFIncyBpbmRleGluZyBiZWdpbnMgZnJvbSAxLg0KDQpgYGB7cn0NCnZfY29sb3JzWzJdICMgV2UgYXJlIHRyeWluZyB0byBleHRyYWN0IHRoZSBzZWNvbmQgZWxlbWVudCBvZiB0aGUgdmVjdG9yLCB2X2NvbG9ycw0Kdl9jb2xvcnNbYygxLDMpXSAgIyBXZSBjYW4gdXNlIHRoZSBjb25jYXRlbmF0aW9uIGZ1bmN0aW9uIHRvIGdldCBub25jb25zZWN1dGl2ZSBlbGVtZW50cy4gSGVyZSwgd2UgYXJlIHRyeWluZyB0byBleHRyYWN0IGVsZW1lbnRzIGluIHBvc2l0aW9ucyAxIGFuZCAzLg0KDQpgYGANCg0KSG93IHdvdWxkIHlvdXIgZXh0cmFjdCBlbGVtZW50cyAxOjksIDE1LCAxOSwgMjAgYW5kIDIxOjMwIGluIGB6emAgYmVsb3c/DQoNCmBgYHtyfQ0Kc2V0LnNlZWQoMTIzNCkNCnp6IDwtIHJub3JtKDEwMCkNCmBgYA0KDQoqKkFuc3dlcjoqKg0KDQpgYGB7cn0NCnp6W2MoMToxOSwxNSwgMTksIDIwOjMwKV0NCmBgYA0KDQpXZSBjYW4gcmVwbGFjZSBlbGVtZW50cyBpbiBzcGVjaWZpYyBwb3NpdGlvbnMuIEJlbG93LCB3ZSByZXBsYWNlIHRoZSBzZWNvbmQgYW5kIHRoaXJkIGNvbG9ycyB3aXRoIGByZWRgIGFuZCBgcHVycGxlYC4NCg0KYGBge3J9DQoodl9jb2xvcnNbMjozXSAgPC0gYygicmVkIiwgInB1cnBsZSIpCSkNCmBgYA0KDQpTb21ldGltZXMgaXQgbWlnaHQgYmUgbW9yZSBjb252ZW5pZW50IHRvIGdldCByaWQgb2YgcGFydGljdWxhciBlbGVtZW50cyBpbnN0ZWFkLiBGb3IgZXhhbXBsZSwgSSBtaWdodCB3YW50IHRvIGV4dHJhY3QgYWxsICoqYnV0KiogdGhlIGZpcnN0IDUgZWxlbWVudHMgb2YgYSB2ZWN0b3IsIG9yIGFsbCBidXQgdGhlIDE1dGggZWxlbWVudC4gV2UgbWlnaHQgZmluZCBpdCBlYXNpZXIgdG8gdXNlIGEgbmVnYXRpdmUgaW5kZXggaGVyZS4NCg0KYGBge3J9DQpqIDwtIGMoLTEsLTIsLTMpDQp4W2pdDQoNCiMgV2UgY291bGQgaGF2ZSBkb25lIHRoYXQgaW4gb25lIGdvIGFzIHdlbGwNCnhbLWMoMTozKV0NCmBgYA0KDQojIyBDb25kaXRpb25hbCBzdWJzZXR0aW5nDQoNCkFub3RoZXIgY29tbW9uIHdheSB0byBzdWJzZXQgaXMgYnkgdXNpbmcgYSBsb2dpY2FsIHZlY3Rvci4gYFRSVUVgIHdpbGwgc2VsZWN0IHRoZSBlbGVtZW50IHdpdGggdGhlIHNhbWUgaW5kZXgsIHdoaWxlIGBGQUxTRWAgd2lsbCBub3QuIFR5cGljYWxseSwgdGhlc2UgbG9naWNhbCB2ZWN0b3JzIGFyZSBub3QgdHlwZWQgYnkgaGFuZCwgYnV0IGFyZSB0aGUgb3V0cHV0IG9mIG90aGVyIGZ1bmN0aW9ucyBvciBsb2dpY2FsIHRlc3RzIHN1Y2ggYXM6DQoNCmBgYHtyfQ0KeCA8LSAxMDA6MTEwDQp4DQoNCnggPjEwNSAjIHJldHVybnMgVFJVRSBvciBGQUxTRSBkZXBlbmRpbmcgb24gd2hpY2ggZWxlbWVudHMgdGhhdCBtZWV0IHRoZSBjb25kaXRpb24NCnNlbGVjdCA8LSB4ID4gMTA1DQp4W3NlbGVjdF0NCmBgYA0KSWYgd2Ugd291bGQgbGlrZSB0aGUgZWxlbWVudHMgdGhhdCBldmFsdWF0ZSB0byBgRkFMU0VgIGluc3RlYWQsIHdlIGNvdWxkIGVhc2lseSB1c2UgdGhlIGAhYCAoYE5PVGApIG9wZXJhdG9yDQoNCmBgYHtyfQ0KeFshc2VsZWN0XQ0KYGBgDQoNCi0tLQ0KDQpZb3UgY2FuIGNvbWJpbmUgbXVsdGlwbGUgdGVzdHMgdXNpbmc6DQoNCi0gYCZgIChgQU5EYCBvcGVyYXRvciAtIGJvdGggY29uZGl0aW9ucyBhcmUgdHJ1ZSkgb3INCg0KLSBgfGAgKGBPUmAgb3BlcmF0b3IgLSBfX2F0IGxlYXN0IG9uZV9fIG9mIHRoZSBjb25kaXRpb25zIGlzIHRydWUpDQoNCldlIGNhbiB0ZXN0IHdoZXRoZXIgeCBpcyBiZXR3ZWVuIHRoZSByYW5nZSAxMDMgYW5kIDEwNjoNCg0KYGBge3J9DQp4W3ggPj0gMTAzICYgeCA8PSAxMDZdDQpgYGANCg0KeCBpcyBncmVhdGVyIHRoYW4gMTAzIGJ1dCAoYEFORGApIGxlc3MgdGhhbiBvciBlcXVhbCB0byAxMDYNCg0KYGBge3J9DQp4W3ggPD0gMTA2ICYgeCA+IDEwM10gIyBvcmRlciBvZiBzdWJzZXR0aW5nIGRvZXMgbm90IG1hdHRlciBoZXJlIQ0KDQpgYGANCg0KeCBpcyBsZXNzIHRoYW4gMTAzIGBvcmAgZ3JlYXRlciB0aGFuIDEwNg0KYGBge3J9DQp4W3ggPj0gMTA2IHwgeCA8IDEwM10NCg0KYGBgDQoNCi0tLQ0KDQpTb21ldGltZXMgd2Ugd2lsbCBuZWVkIHRvIHNlYXJjaCBmb3IgY2VydGFpbiBzdHJpbmdzIGluIGEgdmVjdG9yLiBXaXRoIG11bHRpcGxlIGNvbmRpdGlvbnMsIGl0IGJlY29tZXMgZGlmZmljdWx0IHRvIHVzZSB0aGUgIk9SIiBvcGVyYXRvciBgfGAuIFRoZSBmdW5jdGlvbiBgJWluJWAgYWxsb3dzIHlvdSB0byB0ZXN0IGlmIGFueSBvZiB0aGUgZWxlbWVudHMgb2YgYSBzZWFyY2ggdmVjdG9yIGFyZSBmb3VuZDoNCg0KYGBge3J9DQphbmltYWxzIDwtIGMoIm1vdXNlIiwgInJhdCIsICJkb2ciLCAiY2F0IikNCmFuaW1hbHNbYW5pbWFscyA9PSAiY2F0IiB8IGFuaW1hbHMgPT0gInJhdCJdICMgcmV0dXJucyBib3RoIHJhdCBhbmQgY2F0DQoNCmFuaW1hbHMgJWluJSBjKCJyYXQiLCAiY2F0IiwgImRvZyIsICJkdWNrIiwgImdvYXQiKQ0KYW5pbWFsc1thbmltYWxzICVpbiUgYygicmF0IiwgImNhdCIsICJkb2ciLCAiZHVjayIsICJnb2F0IildDQpgYGANCg0KDQojIyBOYW1lcyBvZiBhIHZlY3Rvcg0KDQpMZXQncyBzYXkgdGhhdCB3ZSB3YW50IHRvIGtub3cgd2hpY2ggY29sb3Igcm9iZSBlYWNoIG9mIDMgcGF0aWVudHMgaXMgd2VhcmluZywgd2UgY2FuIGFzc2lnbiBuYW1lcyB0byB0aGUgdmVjdG9yIG9mIGNvbG9ycy4NCmBgYHtyLCBlY2hvPVRSVUV9DQp2X2NvbG9ycw0KbmFtZXModl9jb2xvcnMpIDwtIGMoIlRob21hcyIsICJMaXoiLCAiVHVja2VyIikNCnZfY29sb3JzDQpgYGANCg0KIyMgQWxnZWJyYWljIE9wZXJhdGlvbnMgb2YgVmVjdG9ycw0KDQpgYGB7ciwgZWNobz1UUlVFfQ0KeCA8LSBjKDEsMiwzKQ0KeSA8LSBjKDQsNSw2KQ0KIyBjb21wb25lbnQtd2lzZSBhZGRpdGlvbg0KeCt5DQojIGNvbXBvbmVudC13aXNlIG11bHRpcGxpY2F0aW9uDQp4KnkNCiMgV2hhdCBoYXBwZW5zIHRvIHRoZSBmb2xsb3dpbmcNCnleeCAjIG9yIHkqKngNCmBgYA0KDQoNCiMjIFJlcGVhdGluZyBWZWN0b3IgaW4gYFJgDQoNCmBgYHtyLCB3YXJuaW5nPVRSVUUsIGVjaG89VFJVRX0NCiMgV291bGQgdGhpcyB3b3JrPw0KYygxLDIsMyw0KSArIGMoMSwyKQ0KIyBXb3VsZCB0aGlzIHdvcms/DQpjKDEsMiwzKSArIGMoMSwyKQ0KYGBgDQoNCipXaHkgdGhlIHdlaXJkIHJlc3VsdHM/Kg0KDQotIFdoZW4geW91IGFyZSBhZGRpbmcgdmVjdG9ycyBvZiB1bmVxdWFsIHNpemUsIGlmIHRoZSBsb25nIG9uZSBpcyBhIG11bHRpcGxlIG9mIHRoZSBzaG9ydCBvbmUsIGBSYCBhdXRvbWF0aWNhbGx5IHJlcGVhdHMgdGhlIHNob3J0IG9uZSB0byBmaWxsIGluIHRoZSBvcGVyYXRpb24uDQoNCmBgYHtyLCBlY2hvID0gVFJVRX0NCjIqYygxLDIsMykNCmBgYA0KDQojIyBNYXRyaXgNCg0KKipDcmVhdGUgYSBuZXcgbWF0cml4KioNCmBgYHtyfQ0KKG1hdHJpeDwtbWF0cml4KDE6MTYsIG5yb3cgPSA0LCBieXJvdyA9IFRSVUUpKQ0KYGBgDQoNCk5vdGUgdGhhdCBgOmAgbWVhbnMgZXZlcnkgbnVtYmVyIGZyb20gMSB0byA0LiBJbiB0aGUgYG1hdHJpeCgpYCBmdW5jdGlvbjoNCg0KMS4gVGhlIGZpcnN0IGFyZ3VtZW50IGlzIHRoZSBjb2xsZWN0aW9uIG9mIGVsZW1lbnRzIHRoYXQgYFJgIHdpbGwgYXJyYW5nZSBpbnRvIHRoZSByb3dzIGFuZCBjb2x1bW5zIG9mIHRoZSBtYXRyaXguIEhlcmUsIHdlIHVzZSAxOjE2IHdoaWNoIGlzIGEgc2hvcnRjdXQgZm9yIGMoMSwgMiwgMywgNCwgLi4uIDE2KS4NCjIuIFRoZSBhcmd1bWVudCBgYnlyb3dgIGluZGljYXRlcyB0aGF0IHRoZSBtYXRyaXggaXMgZmlsbGVkIGJ5IHRoZSByb3dzLiBJZiB3ZSB3YW50IHRoZSBtYXRyaXggdG8gYmUgZmlsbGVkIGJ5IHRoZSBjb2x1bW5zLCB3ZSB1c2UgYGJ5cm93ID0gRkFMU0VgLg0KMy4gVGhlIGFyZ3VtZW50IGBucm93YCBpbmRpY2F0ZXMgdGhhdCB0aGUgbWF0cml4IHNob3VsZCBoYXZlIDQgcm93cy4NCg0KIyMgU2VsZWN0aW9uIG9mIE1hdHJpeCBFbGVtZW50cw0KU2VsZWN0aW9uIG9mIHRoZSBtYXRyaXggZWxlbWVudHMgYXJlIHNpbWlsYXIgdG8gdmVjdG9ycyBleGNlcHQgd2UgaGF2ZSB0d28gZGltZW5zaW9ucyBvdmVyIHdoaWNoIHRvIHN1YnNldC0gcm93cyBhbmQgY29sdW1ucy4NCg0KYGBge3J9DQoNCiMgbWF0cml4W3IsY10gI1N0YW5kYXJkIGZvcm0gb2YgdGhlIG1hdHJpeC4NCg0KbWF0cml4WzEsMl0gI0V4dHJhY3QgZWxlbWVudCBpbiB0aGUgZmlyc3Qgcm93IGFuZCBzZWNvbmQgY29sdW1uDQojRXh0cmFjdCB0aGUgZW50aXJlIGZpcnN0IHJvdyBhbmQgc2Vjb25kIGNvbHVtbnMNCm1hdHJpeFssMToyXQ0KYGBgDQoNCg0KIyMgQXNzaWduIGRpbWVuc2lvbiBuYW1lcyB0byBNYXRyaXgNCg0KYGBge3J9DQoJcm93bmFtZXMobWF0cml4KSA8LSBjKCJZZXMiLCAiTm8iLCAiUGVyaGFwcyIsICJNYXliZSIpDQoJY29sbmFtZXMobWF0cml4KSA8LSBjKCJBcHBsZSIsICJQZWFyIiwgIkJhbmFuYSIsICJHcmFwZXMiKQ0KCW1hdHJpeA0KYGBgDQoNCiMjIERpbWVuc2lvbiBvZiBhIG1hdHJpeCB2cyB2ZWN0b3INCg0KYGBge3J9DQp4IDwtIGMoMSwyLDMpDQptYXRyaXg8LW1hdHJpeCgxOjQsIGJ5cm93ID0gVFJVRSwgbnJvdyA9IDIpDQpsZW5ndGgoeCkNCmxlbmd0aChtYXRyaXgpDQpkaW0obWF0cml4KQ0KZGltKHgpDQpgYGANCg0KDQojIyBMaXN0cw0KDQpgUmAgZG9lc27igJl0IGxpa2UgdmVjdG9ycyB0byBoYXZlIGRpZmZlcmVudCB0eXBlczogYGMoVFJVRSwgMSwgIkZyYW5rIilgIGJlY29tZXMgYGMoIlRSVUUiLCAiMSIsICJGcmFuayIpYC4gQnV0IHN0b3Jpbmcgb2JqZWN0cyB3aXRoIGRpZmZlcmVudCB0eXBlcyBpcyBhYnNvbHV0ZWx5IGZ1bmRhbWVudGFsIHRvIGRhdGEgYW5hbHlzaXMuIGBSYCBoYXMgYSBkaWZmZXJlbnQgdHlwZSBvZiBvYmplY3QgYmVzaWRlcyBhIHZlY3RvciB1c2VkIHRvIHN0b3JlIGRhdGEgb2YgZGlmZmVyZW50IHR5cGVzIHNpZGUtYnktc2lkZTogYSBsaXN0Og0KDQpgYGB7cn0NCmMoVFJVRSwgMSwgIkZyYW5rIikNCnggPC0gbGlzdChUUlVFLCAxLCAiRnJhbmsiKQ0KeA0KYGBgDQoNCk1hbnkgZGlmZmVyZW50IHRoaW5ncyBub3QgbmVjZXNzYXJpbHkgb2Ygc2FtZSBsZW5ndGggY2FuIGJlIHB1dCB0b2dldGhlci4NCg0KYGBge3J9DQp4IDwtIGxpc3QoYygxOjUpLCBjKCJhIiwgImIiLCJjIiksIGMoVFJVRSwgRkFMU0UpLCBjKDVMLCA2TCkpDQp4DQpgYGANCg0KDQojIyBEYXRhZnJhbWVzDQoNCi0gRGF0YSBmcmFtZXMgYXJlIGxpa2Ugc3ByZWFkc2hlZXQgZGF0YSwgcmVjdGFuZ3VsYXIgd2l0aCByb3dzIGFuZCBjb2x1bW5zLg0KLSBJZGVhbGx5IGVhY2ggcm93IHJlcHJlc2VudHMgZGF0YSBvbiBhIHNpbmdsZSBvYnNlcnZhdGlvbiBhbmQgZWFjaCBjb2x1bW4gY29udGFpbnMgZGF0YSBvbiBhIHNpbmdsZSB2YXJpYWJsZSwgb3IgY2hhcmFjdGVyaXN0aWMsIG9mIHRoZSBvYnNlcnZhdGlvbi4NCi0gSXQgcmVwcmVzZW50cyB0aGUgZGF0YSBpbiAgYSB0YWJ1bGFyIGZvcm1hdCB3aGVyZSB0aGUgY29sdW1ucyBhcmUgdmVjdG9ycyB0aGF0IGFsbCBoYXZlIHRoZSBzYW1lIGxlbmd0aC4gQmVjYXVzZSBjb2x1bW5zIGFyZSB2ZWN0b3JzLCBlYWNoIGNvbHVtbiBtdXN0IGNvbnRhaW4gYSBzaW5nbGUgdHlwZSBvZiBkYXRhIChlLmcuLCBjaGFyYWN0ZXJzLCBpbnRlZ2VycywgZmFjdG9ycykuDQotIFdlIGNhbiBvcGVuIGEgZGF0YSB2aWV3ZXIgd2luZG93IHRvIHNlZSB0aGUgY29udGVudHMgb2YgYFJgJ3MgYGlyaXNgIGRhdGEgZnJhbWUgYnkgdHlwaW5nLg0KLSBXZSB3aWxsIGJlIHdvcmtpbmcgd2l0aCBzcHJlYWRzaGVldHMgYSBsb3QuDQoNCmBgYHtyLCBldmFsPUZBTFNFLCBlY2hvPVRSVUV9DQpWaWV3KGlyaXMpDQpgYGANCg0KDQojIyBDcmVhdGUgYSBkYXRhIGZyYW1lDQoNCkRhdGEgZnJhbWUgd2l0aCBIYXJyeSBQb3R0ZXIgY2hhcmFjdGVycw0KDQpgYGB7cn0NCm5hbWUgPC0gYygiSGFycnkiLCAiUm9uIiwgIkhlcm1pb25lIiwgIkhhZ3JpZCIsICJWb2xkZW1vcnQiKQ0KaGVpZ2h0IDwtIGMoMTc2LCAxNzUsIDE2NywgMjMwLCAxODApDQpncGEgPC0gYygzLjQsIDIuOCwgNC4wLCAyLjIsIDMuNCkNCmRmX3N0dWRlbnRzIDwtIGRhdGEuZnJhbWUobmFtZSwgaGVpZ2h0LCBncGEpDQpkZl9zdHVkZW50cw0KYGBgDQoNCi0tLQ0KDQpBbHRlcm5hdGl2ZSB3YXkgb2YgY3JlYXRpbmcgREYNCg0KYGBge3J9DQoJZGZfc3R1ZGVudHMgPC0gZGF0YS5mcmFtZShuYW1lID0gYygiSGFycnkiLCAiUm9uIiwgIkhlcm1pb25lIiwgIkhhZ3JpZCIsICJWb2xkZW1vcnQiKSwNCgkJCQkgIGhlaWdodCA9IGMoMTc2LCAxNzUsIDE2NywgMjMwLCAxODApLA0KCQkJCSAgZ3BhID0gYygzLjQsIDIuOCwgNC4wLCAyLjIsIDMuNCkpDQoJZGZfc3R1ZGVudHMNCmBgYA0KDQoNCiMjIEFkZGluZyB2YXJpYWJsZQ0KDQpgYGB7ciwgZWNobyA9IFRSVUV9DQoJZGZfc3R1ZGVudHMkZ29vZCA8LSBjKDEsIDEsIDEsIDEsIDApDQoJZGZfc3R1ZGVudHMNCmBgYA0KDQoNCiMjIEZlYXR1cmVzIG9mIHRoZSBERg0KDQpgYGB7ciwgZXZhbD1GQUxTRSwgdGlkeT1UUlVFLCB0aWR5Lm9wdHM9bGlzdCh3aWR0aC5jdXRvZmY9NTApLCBlY2hvPVRSVUV9DQoJZGltKGRmX3N0dWRlbnRzKQ0KCWRmX3N0dWRlbnRzWzIsIDNdICAgICAgICAgICAgICAgI1JvbidzIEdQQQ0KCWRmX3N0dWRlbnRzJGdwYVsyXSAgICAgICAgICAgICAgI1JvbidzIEdQQQ0KCWRmX3N0dWRlbnRzWzUsIF0gICAgICAgICAgICAgICAgI2dldCByb3cgNQ0KCWRmX3N0dWRlbnRzWzM6NSwgXSAgICAgICAgICAgICAgI2dldCByb3dzIDMtNQ0KCWRmX3N0dWRlbnRzWywgMl0gICAgICAgICAgICAgICAgI2dldCBjb2x1bW4gMiAoaGVpZ2h0KQ0KCWRmX3N0dWRlbnRzJGhlaWdodCAgICAgICAgICAgICAgI2dldCBjb2x1bW4gMiAoaGVpZ2h0KQ0KCWRmX3N0dWRlbnRzWywgMTozXSAgICAgICAgICAgICAgI2dldCBjb2x1bW5zIDEtMw0KCWRmX3N0dWRlbnRzWzQsIDJdIDwtIDI1NSAgICAgICAgI3JlYXNzaWduIEhhZ3JpZCdzIGhlaWdodA0KCWRmX3N0dWRlbnRzJGhlaWdodFs0XSA8LSAyNTUgICAgI3NhbWUgdGhpbmcgYXMgYWJvdmUNCglkZl9zdHVkZW50cw0KYGBgDQoNCg0KIyMgRXhlcmNpc2UNCg0KTm93IHRoYXQgeW91IGFyZSBlcXVpcHBlZCB3aXRoIHRoZSBiYXNpYywgZ28gYWhlYWQgYW5kIHRha2UgdGhlIGZvbGxvd2luZyBEYXRhY2FtcCBDb3Vyc2UsIFtSIEludHJvIG9uIERhdGFjYW1wXShodHRwczovL2NhbXB1cy5kYXRhY2FtcC5jb20vY291cnNlcy9mcmVlLWludHJvZHVjdGlvbi10by1yKS4gWW91ciBpbnZpdGF0aW9ucyBzaG91bGQgbm93IGJlIGluIHlvdXIgaW5ib3guDQoNCg0KIyBQYXJ0IElWOiBXb3JraW5nIGRpcmVjdG9yaWVzDQoNCllvdSBjYW4gdXNlIHRoZQ0KYGBge3IsIGV2YWwgPSBGQUxTRSwgZWNobz1UUlVFfQ0KZ2V0d2QoKQ0KYGBgDQpjb21tYW5kIHRvIG9idGFpbiB0aGUgY3VycmVudCBkaXJlY3RvcnkgYFJgIGlzIHVzaW5nLg0KDQpJdCBpcyBnb29kIHByYWN0aWNlIHRvIHNldCB0aGUgd29ya2luZyBkaXJlY3RvcnkgbG9jYXRpb24gdG8gd2hlcmUgdGhlIGZpbGVzIGFuZCBkYXRhIGFyZSBzdG9yZWQuDQoNCi0gQ29uc2lkZXIgc2V0dGluZyB5b3VyIHdvcmtpbmcgZGlyZWN0b3J5IHRvIGEgZm9sZGVyIGNhbGxlZCBBQUVDNDk4NCwgQUFFQzU0ODQsIG9yIFNUQVQ1NDg0IG9uIHlvdXIgZGVza3RvcCAoZm9yIGV4YW1wbGUpLg0KDQojIyBDcmVhdGluZyBEaXJlY3RvcnkgYW5kIFNldCB3b3JraW5nIGRpcmVjdG9yeQ0KDQoqKldpbmRvd3MqKg0KYGBge3IsIHRpZHk9VFJVRSwgdGlkeS5vcHRzPWxpc3Qod2lkdGguY3V0b2ZmPTUwKSxldmFsID0gRkFMU0UsIGVjaG89VFJVRX0NCiAgc2V0d2QoIkM6L3VzZXJzL1t5b3VyIHVzZXIgbmFtZV0vRGVza3RvcC9BQUVDNDk4NC8iKQ0KICAjIE9SDQogIHNldHdkKCJDOlxcdXNlcnNcXFt5b3VyIHVzZXIgbmFtZV1cXERlc2t0b3BcXEFBRUM0OTg0XFwiKQ0KICAjIG5vdGljZSB0aGUgZG91YmxlIGJhY2tzbGFzaGVzDQpgYGANCg0KKipNYWMqKg0KYGBge3IsIGV2YWwgPSBGQUxTRSwgZWNobz1UUlVFfQ0KICBzZXR3ZCgifi9EZXNrdG9wL0FBRUM0OTg0IikNCmBgYA0KDQotIFRvIGNoZWNrIHdoZXRoZXIgdGhlIHdkIGlzIGNvcnJlY3QsIHdlIGFnYWluIHVzZQ0KDQpgYGB7ciwgZXZhbCA9IEZBTFNFLCBlY2hvPVRSVUV9DQpnZXR3ZCgpDQpgYGANCg0KLSBUbyBvYnRhaW4gYSBsaXN0IG9mIHRoZSBuYW1lcyBvZiBmaWxlcyBvciBmb2xkZXJzIGluIHRoZSB3b3JraW5nIGRpcmVjdG9yeSwgd2UgY2FuIHVzZQ0KDQpgYGB7ciwgZXZhbCA9IEZBTFNFLCBlY2hvPVRSVUV9DQpkaXIoKQ0KYGBgDQoNCi0gVG8gY3JlYXRlIGEgbmV3IGZvbGRlciBpbiB5b3VyIGRpcmVjdG9yeSB3ZSBjYW4gdXNlDQpgYGB7ciwgZXZhbCA9IEZBTFNFfQ0KZGlyLmNyZWF0ZSgiW0ZvbGRlciBuYW1lXSIpDQpgYGANCg0KIyMgSW1wb3J0aW5nIGRhdGENCg0KYFJgIGFsbG93cyB1cyB0byBpbXBvcnQgc2V2ZXJhbCBmaWxlIHR5cGVzLiBJIHdpbGwgZGlzY3VzcyAzIHRoYXQgd2UgYXJlIG1vc3QgbGlrZWx5IHRvIHVzZSBpbiB0aGlzIGNvdXJzZS4NCg0KMS4gVGV4dCBmaWxlcw0KOiBEYXRhIHNvbWV0aW1lcyBjb21lIHdpdGggaGVhZGVycyAodGhlIGZpcnN0IHJvdyBpcyB2YXJpYWJsZSBuYW1lcywgbm90IGFjdHVhbCBkYXRhISkgWW91IG5lZWQgdG8gdGVsbCBSIHRoYXQhDQoNCmBgYHtyLCBldmFsPSBGQUxTRSwgZWNobz1UUlVFfQ0KdGV4dGRhdGE8LXJlYWQudGFibGUoImV4YW1wbGVzL2hvZ3NkYXRhLnR4dCIsaGVhZGVyPVQpDQpgYGANCg0KMi4gQ1NWIGZpbGVzDQo6DQpgYGB7cixldmFsPUZBTFNFLCBlY2hvID0gRkFMU0V9DQpjc3ZkYXRhIDwtIHJlYWQuY3N2KCJleGFtcGxlcy9ob2dzZGF0YS5jc3YiLGhlYWRlcj1UKQ0KYGBgDQoNCjMuIHhsc3ggZmlsZXMgKHJlcXVpcmVzIG9wZW54bHN4IHBhY2thZ2UpDQpgYGB7ciwgZXZhbD0gRkFMU0UsIGVjaG89VFJVRX0NCnhsc3hkYXRhIDwtIHJlYWQuY3N2KCJleGFtcGxlcy9ob2dzZGF0YS54bHN4IiwgLi4uICkNCmBgYA0KDQoNCiMjIEZ1bmN0aW9ucyAmIFBhY2thZ2VzDQoNCkZ1bmN0aW9ucyBhcmUg4oCcY2FubmVkIHNjcmlwdHPigJ0gdGhhdCBhdXRvbWF0ZSBtb3JlIGNvbXBsaWNhdGVkIHNldHMgb2YgY29tbWFuZHMgaW5jbHVkaW5nIG9wZXJhdGlvbnMgYXNzaWdubWVudHMsIGV0Yy4gRm9yIHRoZSBwdXJwb3NlIG9mIHRoaXMgY291cnNlLCB3ZSB3aWxsIHVzZSBhIGxvdCBvZiBmdW5jdGlvbnMgdGhhdCBhcmUgYnVpbHQgYm90aCBpbiBiYXNlIFIgKHRoYXQgaXMsIHRoZXkgYXJlIHByZWRmaW5lZCkgb3IgYXZhaWxhYmxlIHRocm91Z2ggUiBwYWNrYWdlcyAoZGlzY3VzcyBiZWxvdykuDQoNCkEgZnVuY3Rpb24gdXN1YWxseSB0YWtlcyBvbmUgb3IgbW9yZSBpbnB1dHMgY2FsbGVkICphcmd1bWVudHMqLCBhbmQgb2Z0ZW4gKGJ1dCBub3QgYWx3YXlzKSByZXR1cm4gYSAqdmFsdWUqLg0KDQotLS0NCg0KQ29uc2lkZXIgZm9yIGV4YW1wbGUsIHRha2luZyB0aGUgYXZlcmFnZSBvZiBhIHNldCBvZiByYW5kb20gbnVtYmVycyAoeCkuDQoNCmBgYHtyLCByZXN1bHRzPSdtYXJrdXAnLCBlY2hvPVRSVUV9DQpzZXQuc2VlZCgxMjQpDQp4IDwtIHJub3JtKDYpICogMTAwDQoocm91bmQoeCwgZGlnaXRzPTIpKSAjIHJvdW5kIGZ1bmN0aW9uID0+IDJkcA0KYGBgDQoNCklmIHdlIHdlcmUgdG8gZG8gdGhpcyBtYW51YWxseSwgd2Ugd291bGQ6DQoNCjEuIFN1bSB1cCB0aGUgdmFsdWVzDQpgYGB7ciwgZWNobz1UUlVFfQ0Kc3VteCA8LSBzdW0oeCkNCmBgYA0KDQoyLiBHZXQgdGhlIG51bWJlciBvZiBvYnNlcnZhdGlvbnMNCmBgYHtyLCBlY2hvPVRSVUV9DQpueCA8LSBsZW5ndGgoeCkNCmBgYA0KDQozLiBEaXZpZGUgc3VtIGJ5IHRvdGFsIG51bWJlciBvZiBvYnNlcnZhdGlvbnMNCg0KYGBge3IsIGVjaG89VFJVRX0NCm1lYW54IDwtIHN1bXgvbngNCmBgYA0KDQpVc2luZyBgUmAncyBidWlsdCBpbiBgbWVhbmAgZnVuY3Rpb24gd2UgY2FuIGRvIGFsbCB0aHJlZSBzdGVwcyBpbnRlcm5hbGx5IGFuZCBjcm9zcyBjaGVjayBhZ2FpbnN0IG91ciBtYW51YWwgY2FsY3VsYXRpb25zLg0KDQpgYGB7ciwgZWNobz1UUlVFfQ0KbWVhbih4KQ0KbWVhbnggPT0gbWVhbih4KSAjIGNyb3NzIHZhbGlkYXRpb24NCmBgYA0KDQojIyBJbnN0YWxsaW5nIFBhY2thZ2VzDQoNClNpbmNlIFIgaXMgYW4gT3BlbiBTb3VyY2Ugc29mdHdhcmUgcHJvZ3JhbSwgdGhvdXNhbmRzIG9mIHBlb3BsZSBjb250cmlidXRlIHRvIHRoZSBzb2Z0d2FyZS4gVGhleSBkbyB0aGlzIGJ5IHdyaXRpbmcgY29tbWFuZHMgKGNhbGxlZCBmdW5jdGlvbnMpIHRvIG1ha2UgYSBwYXJ0aWN1bGFyIGFuYWx5c2lzIGVhc2llciwgb3IgdG8gbWFrZSBhIGdyYXBoaWMgcHJldHRpZXIuDQoNCldoZW4geW91IGRvd25sb2FkIFIsIHlvdSBnZXQgYWNjZXNzIHRvIGEgbG90IG9mIGZ1bmN0aW9ucyB0aGF0IHdlIHdpbGwgdXNlLiBIb3dldmVyIHRoZSBvdGhlciB1c2VyLXdyaXR0ZW4gcGFja2FnZXMgd2UgdXNlIGZvciBvdXIgYW5hbHlzZXMgd2lsbCBtYWtlIG91ciBsaXZlcyBtdWNoIGVhc2llci4NCg0KRm9yIGV4YW1wbGUsIHRob3VnaCB3ZSBjYW4gdXNlIHRoZSBgcGxvdGAgY29tbWFuZCBmb3Igc3RhbmRhcmQgZ3JhcGhpY3MsIHlvdSB3aWxsIHF1aWNrbHkgc2VlIHRoYXQgd2UgY2FuIGdldCBtdWNoIGJldHRlciBsb29raW5nIHRpbWUgZ3JhcGhzIHVzaW5nIHRoZSBgZnBwMmAgcGFja2FnZSAod2hpY2ggYWxzbyB1c2VzIGFub3RoZXIgcGFja2FnZSBjYWxsZWQgYGdncGxvdDJgKS4NCg0KDQojIyBJbnN0YWxsaW5nIFBhY2thZ2VzDQoNClRvIGluc3RhbGwgdGhlIGBmcHAyYCBwYWNrYWdlLCB3ZSBjYW4gdXNlIHRoZSBjb21tYW5kDQpgYGB7ciwgZXZhbD1GQUxTRSwgZWNobz1UUlVFfQ0KaW5zdGFsbC5wYWNrYWdlcygiZnBwMiIpDQpgYGANCldlIHdpbGwgbmVlZCB0byBpbnN0YWxsIGEgcGFja2FnZSBvbmx5IG9uY2UgaW4gYFJgLg0KDQpOb3cgdGhhdCB5b3UgaGF2ZSB0aGUgYGZwcDJgIHBhY2thZ2UgaW5zdGFsbGVkLCB3ZSBjYW4gY2hlY2sgdG8gc2VlIGlmIGl0IGlzIGluIHVzZQ0KYGBge3IgZXZhbD1GQUxTRSwgZWNobz1UUlVFfQ0Kc2VhcmNoKCkNCmBgYA0KDQpMYXN0bHksIGluIG9yZGVyIHRvIHVzZSB0aGUgcGFja2FnZSwgd2Ugd2lsbCBuZWVkIHRvIGxvYWQgdGhlIGxpYnJhcnkNCmBgYHtyIGV2YWw9VFJVRSwgbWVzc2FnZT0gRkFMU0UsIGVjaG89VFJVRX0NCmxpYnJhcnkoZnBwMikNCmBgYA0KDQojIyBVc2luZyBsaWJyYXJpZXMNCg0KVGhlIGBmcHAyYCBwYWNrYWdlIGNvbnRhaW5zIGEgbnVtYmVyIG9mIHVzZWZ1bCBkYXRhc2V0cy4gT25lIHN1Y2ggZGF0YSBzZXQgaXMgYGgwMmAuDQoNClVzZSB0aGUgYGhlbHAoKWAgZnVuY3Rpb24gdG8gZ2V0IGEgZGVjcmlwdGlvbiBvZiB0aGlzIGRhdGEuIFRyeQ0KYGBge3IsZXZhbD0gRkFMU0UsIGVjaG89VFJVRX0NCmhlbHAoaDAyKQ0KYGBgDQoNCk5vdyBsZXQgdXMgY3JlYXRlIGEgbmljZSBwbG90IG9mIHRoZSBgaDAyYCBkYXRhDQoNCmBgYHtyICwgZmlnLmhlaWdodD0gMi41LCBlY2hvPVRSVUV9DQphdXRvcGxvdChoMDIpDQpgYGANCg0KLS0tDQoNCkxldCB1cyBsZWF2ZSBpdCB0aGVyZSBmb3Igbm93IQ0KDQotLS0NCg0KDQoNCg0K
2.1 Comments
Whenever possible, use comments! Anything following the symbol
#in an R Script will not be run in R.Comments are notes we leave ourselves so we know:
I promise that this will become useful when you come back to your code after an extended time. I cannot tell you the number of times I have had a moment of pure genius while coding and I spend hours on a different day trying to understand why I coded it like that or what I actually did.
For example, below is the type of comments that I always include in my programs
You can also understand the following code without even knowing what exactly each line of command does because I tell you what they are!